package mpscheduling;

import java.util.*;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author jesseday
 */
public class Processor implements Runnable{
    
    public int pnum;
    private AtomicInteger time;
    public ArrayList<Process> ReadyQueue;
    private LinkedList<Integer> Gantt;
    private Semaphore mutex;
    public Process currentProcess;
    public int algo;
    private int start;
    public int quantum;
    
    public Processor(int pnum, AtomicInteger time, ArrayList rq, 
        LinkedList gantt, Semaphore mutex, int algo, int q)
    {
        this.pnum = pnum;
        this.time = time;
        this.ReadyQueue = rq;
        this.Gantt = gantt;
        this.mutex = mutex;
        this.algo = algo;
        this.quantum = q;
        start = 0;
    }

    @Override
    public void run()
    {
        try {


            mutex.acquire();

            if(algo==0)
                insertionSort(ReadyQueue);
            

            if(currentProcess != null)
            {
                if(!ReadyQueue.isEmpty())
                {
                    if(algo==0)
                    {
                        if(currentProcess.remainingTime() > ReadyQueue.get(0).remainingTime())
                        {
                            ReadyQueue.add(currentProcess);
                            currentProcess = ReadyQueue.remove(0);
                        }
                    }else if(algo==1)
                    {
                        if(time.get()-start==quantum)
                        {
                            ReadyQueue.add(currentProcess);
                            currentProcess = ReadyQueue.remove(0);
                            start = time.get();
                        }
                    }
                }
                
                if(currentProcess.isDone())
                {
                    currentProcess = null;
                    if(!ReadyQueue.isEmpty())
                    {
                        currentProcess = ReadyQueue.remove(0);
                        start = time.get();
                    }
                }
                
            }else if(!ReadyQueue.isEmpty())
            {
                currentProcess = ReadyQueue.remove(0);
                start = time.get();
            }

            mutex.release();

            if(currentProcess != null)
            {
                currentProcess.run();

                Gantt.add(currentProcess.processNum());
            }else {
                Gantt.add(0);
            }
        
        } catch (InterruptedException ex) {
                Logger.getLogger(Processor.class.getName()).log(Level.SEVERE, null, ex);
            }
        
    }
    
    private void insertionSort(ArrayList<Process> Queue)
    {

        for(int i = 1; i < Queue.size(); i++)
        {
            for(int j = i; (j > 0) && (Queue.get(j).remainingTime()<Queue.get(j-1).remainingTime()); j--)
            {
                //Swap RQ[j],RQ[j-1]
                Queue.add(j-1, Queue.get(j));
                Queue.remove(j+1);
            }
        }
    }
}
